#include <iostream>
#include <vector>
#include "TypeBase.hpp"
#include "Value.hpp"
#include "3adCode.hpp"

/*
 *
bool TypeBase::operator==( const Type &toCompare ){

	switch ( toCompare.theType ) {
		case TYPE_INTEGER:	
		case <-LABEL->:	
		case <-LABEL->:	

		default:	
			break;
	}			
	return false;
}

bool TypeBase::operator!=(const Type &toCompare ) {
	return !( *this == toCompare );
}
*/



TypeTemp::TypeTemp() {
	this->theType = TYPE_TEMP;
	this->idTemp = -1;
	this->finalType = NULL;
}

TypeTemp::TypeTemp(int idTmp) {
	this->theType = TYPE_TEMP;
	this->idTemp = idTmp;
	this->finalType = NULL;
}

void TypeTemp::show() {
	if(this->finalType == NULL ){
		std::cout << "TempType_id_"<< this << "_" << this->idTemp;
	} else {
		std::cout << "<identifiant_" << idTemp << ">";
			//finalType->show();
	}
}

Type * TypeTemp::clone() {
	//Type * t = new TypeTemp(this->idTemp);
	return this;
}

void TypeTemp::setType(Type* type){
	this->finalType = type;
}
/* ******************************************************
 * ****************** IntegerType
 * ****************************************************** */
TypeInteger::TypeInteger() {
	this->theType = TYPE_INTEGER;
}
int TypeInteger::getOrd(Value *val) {
	return  val->getInteger();
}
void TypeInteger::show() {
	std::cout<<"integer";
}

Type * TypeInteger::clone() {
	Type * t = new TypeInteger();
	return t;
}

bool TypeInteger::isApplicable(CodeInstruction operation) {
	switch (operation) {
		case OPCODE_ADD:
		case OPCODE_SUB:
			return true;
		default:
			return false;
	}
}

/* ******************************************************
 * ******************  TypeReal
 * ****************************************************** */

TypeReal::TypeReal() {
	this->theType = TYPE_REAL;
}
int TypeReal::getOrd(Value *val) {
	return  val->getReal();
}
void TypeReal::show() {
	std::cout<<"reel";
}

Type * TypeReal::clone() {
	Type * t = new TypeReal();
	return t;
}

bool TypeReal::isApplicable(CodeInstruction operation) {
	switch (operation) {
		case OPCODE_ADD:
		case OPCODE_SUB:
			return true;
		default:
			return false;
	}
}

/* ******************************************************
 * ******************  TypeBoolean
 * ****************************************************** */

TypeBoolean::TypeBoolean() {
	this->theType = TYPE_BOOLEAN;
}

void TypeBoolean::show() {
	std::cout<<"booleen";
}

Type * TypeBoolean::clone() {
	Type * t = new TypeBoolean();
	return t;
}

bool TypeBoolean::isApplicable(CodeInstruction operation) {
	switch (operation) {
	case OPCODE_AND:
	case OPCODE_OR:
	case OPCODE_NOT:
		return true;
	default:
		return false;
	}
}



/* ******************************************************
 * ******************  TypeChar
 * ****************************************************** */

TypeChar::TypeChar() {
	this->theType = TYPE_CHAR;
}
int TypeChar::getOrd(Value *val) {
	return  val->getChar();
} 
void TypeChar::show() {
	std::cout<<"caractere";
}

Type * TypeChar::clone() {
	Type * t = new TypeChar();
	return t;
}


/* ******************************************************
 * ******************  TypeString
 * ****************************************************** */

TypeString::TypeString() {
	this->theType = TYPE_STRING;
}
void TypeString::show() {
	std::cout<<"string";
}

Type * TypeString::clone() {
	Type * t = new TypeString();
	return t;
}


/* ******************************************************
 * ******************  TypeString
 * ****************************************************** */

TypeNil::TypeNil() {
	this->theType = TYPE_NIL;
}
void TypeNil::show() {
	std::cout<<"nil";
}
Type * TypeNil::clone() {
	Type * t = new TypeNil();
	return t;
}
